package istar.behaviour;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import jade.core.AID;
import jade.core.behaviours.Behaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import istar.IElement;
import istar.IistarBehaviour;
import istar.agent.IstarJadeAgent;
import istar.impl.AbstractMainGoal;

public class IstarMainBehaviour extends Behaviour implements IistarBehaviour{
	
	
	private static final int initial = 0;
	private static final int wating_request = 1;
	private static final int done = 2;
	private AbstractMainGoal mainGoal;
	private HashMap<String, ArrayList<AID>> committed = new HashMap<String, ArrayList<AID>>();

	private int step=initial;
	
	public IstarMainBehaviour(AbstractMainGoal _mainGoal){
		super();
		step=0;
		this.mainGoal = _mainGoal;
	}
	
	public IstarMainBehaviour(IstarJadeAgent _agent, AbstractMainGoal _mainGoal){
		super(_agent);
		step=0;
		this.mainGoal = _mainGoal; 
	}

	
	
	@Override
	public long getEstimatedWaitingTime() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getExecutionNumber() {
		// TODO Auto-generated method stub
		return null;
	}
	
	public void log(String _phrase){
		((IstarJadeAgent)myAgent).log(_phrase);
	}

	@Override
	public void action(){
		String ticket;
		switch (step) {
		case initial:
			this.committed.clear();
			mainGoal.clear();
			
			ACLMessage msgReply = null;
			AID receiver = null;
			// checking existence of wainting messages to this goal
			ticket = ((IstarJadeAgent)myAgent).getTicket();
			ACLMessage msgWaiting = ((IstarJadeAgent)myAgent).getWaitingMessages().get(ticket);
			if (msgWaiting!= null ){
				System.out.println(this.getBehaviourName()+ " received waiting msg topic:"+msgWaiting.getUserDefinedParameter("topic"));
				
				if (msgWaiting.getUserDefinedParameter("topic").equals(mainGoal.getDependumToThisElement().getTopic())){
					log("There is a 'WAITING' message from agent " + msgWaiting.getSender().getName()+ " with content: " + msgWaiting.getContent() );
					msgReply = msgWaiting.createReply();
					receiver = msgWaiting.getSender();
				}
			}
			// checking existence of proposal messages
			else{
				TopicMatchExpression tm = new TopicMatchExpression(mainGoal.getDependumToThisElement().getTopic(), ACLMessage.PROPOSE);
				MessageTemplate mtPropose = new MessageTemplate(tm);
				//MessageTemplate mtPropose = MessageTemplate.MatchPerformative(ACLMessage.PROPOSE);
				ACLMessage msgPropose = myAgent.receive(mtPropose);
				if (msgPropose!=null ){
					System.out.println(this.getBehaviourName()+ " received propose msg topic:"+msgPropose.getUserDefinedParameter("topic"));
					log(this.getBehaviourName()+ " received propose msg topic:"+msgPropose.getUserDefinedParameter("topic"));
					//if (msgPropose.getUserDefinedParameter("topic").equals(mainGoal.getDependumToThisElement().getTopic())){
						msgReply = msgPropose.createReply();
						receiver = msgPropose.getSender();
						log("Received a 'PROPOSAL' message from agent " + msgPropose.getSender().getName()+ " with content: " + msgPropose.getContent() );
						
					//}
				}
			}

			if (msgReply!=null ){
				System.out.println(this.getBehaviourName()+ " received reply msg topic:"+msgReply.getUserDefinedParameter("topic"));

				if (msgReply.getUserDefinedParameter("topic").equals(mainGoal.getDependumToThisElement().getTopic())){
					msgReply.setPerformative(IistarBehaviour.READY);
					myAgent.send(msgReply);
					Iterator<AID> itReceivers = msgReply.getAllReceiver();
					while (itReceivers.hasNext()){
						log("Sending a 'READY' message to agents " + itReceivers.next().getName()+ " with content: " + msgReply.getContent() );
					}

					ArrayList<AID> commitedAgents = this.committed.get(ticket);
					if (commitedAgents==null){
						commitedAgents = new ArrayList<AID>();
					}
					commitedAgents.add(receiver);
					committed.put(ticket, commitedAgents);
					step = wating_request;
					
				}
			}
			break;

		case wating_request:
			//MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.REQUEST);
			TopicMatchExpression tm = new TopicMatchExpression(mainGoal.getDependumToThisElement().getTopic(), ACLMessage.REQUEST);
			MessageTemplate mt = new MessageTemplate(tm);
			ACLMessage msgRequest = myAgent.receive(mt);
			if (msgRequest!=null ){
				System.out.println(this.getBehaviourName()+ " received request msg topic:"+msgRequest.getUserDefinedParameter("topic"));
				if (msgRequest.getUserDefinedParameter("topic").equals(mainGoal.getDependumToThisElement().getTopic())){
					ticket = ((IstarJadeAgent)myAgent).getNextTicket();
					((IstarJadeAgent)myAgent).getWorkingMessages().put(ticket,msgRequest);
					mainGoal.setExecutionNumber(ticket);
					log("Agent name="+ myAgent.getName() +": executing. Ticket="+ mainGoal.getExecutionNumber());
					mainGoal.deliberate();
					
					//changed here
					//String content = msgRequest.getContent();
					Object content=null;
					try {
						content = msgRequest.getContentObject();
					} catch (Exception e) {
						e.printStackTrace();
					}
					
					//changed here
					//mainGoal.getContent().add(content);
					//((IstarJadeAgent)myAgent).setKnowledgeElement(mainGoal.getExecutionNumber(), mainGoal);
					((IstarJadeAgent)myAgent).setParameter(mainGoal.getExecutionNumber(), mainGoal.getName(), content);
					((IstarJadeAgent)myAgent).setKnowledgeObject(mainGoal.getExecutionNumber(), "Message-Received", msgRequest);
					log("Agent name="+ myAgent.getName() +" received a REQUEST for:" + content);
					step=done;
				}
			}
			
			break;
		default:
			break;
		}
		
	}

	@Override
	public int onEnd() {
		if (step==done){
			step = 0;
			mainGoal.undeliberate();
			return 1;
		}
		else{
			return 0;
		}
	}

	@Override
	public boolean done() {
		return (step==done);
	}


}
